
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
//#include <QLineEdit>
#include <QToolButton>
#include <QSpinBox>
#include <QMessageBox>
#include <QApplication>
#include <QAction>
#include <QMenuBar>
#include <QMenu>
#include <QListWidget>
#include <QListWidgetItem>
#include <QDir>
#include <QSettings>
//#include <QCloseEvent>
#ifdef DEBUG
#include <QtDebug>
#endif

#include "mainwindow.h"
#include "dictengine.h"
#include "meaningdialog.h"
#include "settingsdialog.h"
#include "lineedit.h"

int DictEngine::number_of_suggestions;

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
	QCoreApplication::setAttribute(Qt::AA_S60DisablePartialScreenInputMode, false);

	databaseNameLabel = new QLabel();
	lineEdit1 = new LEdit(this);
	listWidget = new QListWidget(this);
	swapButton = new QToolButton();
	swapButton->setIcon(QIcon(":/images/swap.png"));
	swapButton->setEnabled(false);

	QHBoxLayout *hl1 = new QHBoxLayout;
	hl1->addWidget(lineEdit1);
	hl1->addWidget(swapButton);

	QVBoxLayout *vl1 = new QVBoxLayout;
	vl1->addSpacing(10);
	vl1->addLayout(hl1);
//	vl1->addSpacing(10);
	vl1->addWidget(databaseNameLabel);
	vl1->addWidget(listWidget);

	QWidget *w1 = new QWidget;
	w1->setLayout(vl1);

	setCentralWidget(w1);
	foreach(QWidget *widget, findChildren<QWidget *>())
		widget->setContextMenuPolicy(Qt::NoContextMenu);

	connect(lineEdit1, SIGNAL(textEdited(QString)), this, SLOT(hints(QString)));
	connect(lineEdit1, SIGNAL(returnPressed()), this, SLOT(showFirstMeaning()));
	connect(listWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(showMeaning()));
	connect(swapButton, SIGNAL(clicked()), this, SLOT(swapLanguage()));

	meaningDialog = NULL;
	dictEngine = NULL;

	readSettings();
	QCoreApplication::postEvent(lineEdit1, new QEvent(QEvent::RequestSoftwareInputPanel));
	createMenus();
	setStyleSheet("QToolButton{ background-color: transparent;"
				  "border-style: outset; border-color: transparent;"
				  "border-width: 0px; padding: 0px;"
				  "icon-size: 34px}");
}

MainWindow::~MainWindow()
{
	delete dictEngine;
	saveSettings();
}

void MainWindow::hints(QString query) {
	listWidget->clear();
	if(query.length() < minQueryLength || dictEngine == NULL)
		return;
	listWidget->setEnabled(true);
	QStringList strl = dictEngine->suggestions(query);
	if(strl.length() == 0) {
		strl << QStringList(tr("No hits"));
		listWidget->setEnabled(false);
	}
	listWidget->insertItems(0, strl);
	listWidget->scrollToTop();
}

void MainWindow::showMeaning()
{
	if(meaningDialog != NULL)	/* this ensures only one instance of MeaningDialog exists */
		return;
	meaningDialog = new MeaningDialog(this);
	meaningDialog->setText(dictEngine->meaning(listWidget->hasFocus() ?
											   listWidget->currentRow() : 0));
	meaningDialog->exec();
	delete meaningDialog;
	meaningDialog = NULL;
}

void MainWindow::showFirstMeaning()
{
	int _minQueryLength = minQueryLength;
	minQueryLength = 1;
	hints(lineEdit1->text());
	minQueryLength = _minQueryLength;
	showMeaning();
}

void MainWindow::switchDatabase()
{
	QAction *action = qobject_cast<QAction *>(sender());
	switchDatabase(action->text());
}

void MainWindow::switchDatabase(QString datName)
{
	delete dictEngine;
	dictEngine = NULL;
	swapButton->setEnabled(false);
	QString str = "<span style=\"font-size:16px\">&nbsp;&nbsp;"
				  + tr("No database loaded.") + "</span>";
	if(datName.length() == 0) {
		databaseNameLabel->setText(str);
		return;
	}
	try {
#ifdef Q_OS_SYMBIAN
		dictEngine = new DictEngine(databasePath, datName, this);
#else	/* Qt Simulator */
		dictEngine = new DictEngine(".", datName, this);
#endif
		str = "<span style=\"font-size:16px\">&nbsp;&nbsp;"
			  + dictEngine->name() + "</span>";
		QStringList sl = datName.split("-");
		swapButton->setEnabled(sl.length() == 2 && databaseNames.contains(sl[1] + "-" + sl[0]));
	}
	catch(QString ex) {
		QMessageBox::warning(this, tr("Open database"), ex);
		dictEngine = NULL;
	}
	databaseNameLabel->setText(str);
	hints(lineEdit1->text());
}

void MainWindow::swapLanguage()
{
	QStringList sl = dictEngine->databaseName().split("-");
	switchDatabase(sl[1] + "-" + sl[0]);
}

void MainWindow::updateSettings()
{
	SettingsDialog sd(databasePath, minQueryLength,
					  DictEngine::number_of_suggestions, this);
	if(sd.exec()) {
		databasePath = sd.path->text();
		minQueryLength = sd.minQueryLength->value();
		DictEngine::number_of_suggestions = sd.numberOfSuggestions->value();
		hints(lineEdit1->text());
	}
}

void MainWindow::createMenus()
{
	QMenu *databasesMenu = menuBar()->addMenu(tr("Databases"));
	QAction *action;
	foreach(QString name, databaseNames) {
		action = new QAction(name, this);
		connect(action, SIGNAL(triggered()),
				this, SLOT(switchDatabase()));
		databasesMenu->addAction(action);
	}
//	action = new QAction("jedna-dva", this);	//	test action
//	connect(action, SIGNAL(triggered()),
//			this, SLOT(switchDatabase()));
//	databasesMenu->addAction(action);

	QAction *settingsAction = new QAction(tr("Settings"), this);
	connect(settingsAction, SIGNAL(triggered()), this, SLOT(updateSettings()));
	menuBar()->addAction(settingsAction);

	QAction *aboutAction = new QAction(tr("About"), this);
	connect(aboutAction, SIGNAL(triggered()), this, SLOT(showAboutProgram()));
	menuBar()->addAction(aboutAction);

	QAction *exitAction = new QAction(tr("Exit"), this);
	connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
	menuBar()->addAction(exitAction);
}

void MainWindow::loadDatabaseNames()
{
	QDir dir(databasePath);
	dir.setFilter(QDir::Files);
	dir.setSorting(QDir::Name);
	QStringList files = dir.entryList();
	QString str;
	foreach(QString file, files)
		if(file.right(6) == ".index") {
			str = file.left(file.length() - 6);
			if(files.contains(str + ".dict"))
				databaseNames.append(str);
		}
	if(databaseNames.length() == 0)
		QMessageBox::warning(this, tr("Warning"),
							 tr("No dictionary database files found. Path: %1").arg(databasePath));
}

void MainWindow::readSettings()
{
	QSettings settings("XY Software", "S3Dict");
	databasePath = settings.value("Database path", "F:/Documents/Slovniky").toString();
	loadDatabaseNames();
	DictEngine::number_of_suggestions = settings.value("Number of suggestions", 20).toInt();
	QString currentDatabase = settings.value("Current database", "").toString();
	if(currentDatabase.length() == 0 && databaseNames.length() > 0)
		currentDatabase = databaseNames.at(0);
	else if(databaseNames.length() == 0)
		currentDatabase = "";
	switchDatabase(currentDatabase);
	minQueryLength = settings.value("Minimum query length", 3).toInt();
	lineEdit1->setText(settings.value("Search term", "").toString());
	hints(lineEdit1->text());
}

void MainWindow::saveSettings() const
{
	QSettings settings("XY Software", "S3Dict");
	if(dictEngine) settings.setValue("Current database", dictEngine->databaseName());
	settings.setValue("Minimum query length", minQueryLength);
	settings.setValue("Database path", databasePath);
	settings.setValue("Number of suggestions", DictEngine::number_of_suggestions);
	settings.setValue("Search term", lineEdit1->text());
}

void MainWindow::showAboutProgram() {
	QString aboutStr =  "<h2>S3Dict</h2>"
					+ tr("S3Dict is a mobile dictionary app compatible with *.index/*.dict format. "
						 "See %1 for more information.")
					.arg("<a href=\"http://projects.developer.nokia.com/S3Dict\">projects.developer.nokia.com/S3Dict</a>");

	if(meaningDialog != NULL)
		return;
	meaningDialog = new MeaningDialog(this);
	meaningDialog->setText(aboutStr);
	meaningDialog->exec();
	delete meaningDialog;
	meaningDialog = NULL;
}


//void MainWindow::closeEvent(QCloseEvent *event)
//{
//	if(lineEdit1->text().length() > 0) {
//		lineEdit1->setText("");
//		event->ignore();
//	}
//}

